/**
 * 请实现如下的函数，可以批量请求数据，
 * 所有的URL地址在urls参数中，同时可以
 * 通过max参数控制请求的并发数，当所有
 * 请求结束后，需要执行callback回调函数。
 * 发请求的函数可以直接使用fetch即可
 */

/**
 * 批量请求函数
 * @param urls 请求urls
 * @param max 最大请求数
 * @param callback 回调函数
 */
export async function sendRequest(urls: string[], max = 3, callback: (data: any) => void) {
  // 取urls和max的最小值
  const min = Math.min(urls.length, max);
  // 发出请求函数
  const requestList = urls.map(url => () => request(url));
  const promises: Promise<any>[] = [];
  const pool = new Set<Promise<string>>();

  for (const request of requestList) {
    const promise = request();
    // 请求结束后，从pool中删除
    const cb = () => pool.delete(promise);

    // 注册任务
    promise.then(cb, cb);
    pool.add(promise);
    promises.push(promise);

    if (pool.size >= min) {
      // 请求池满了，执行race，竞争执行，先成功先失败
      await Promise.race(pool).catch(err => console.error(err));
    }
  }

  // 异步有了结果后在调用会立即执行之前的结果
  Promise.allSettled(promises).then(callback);
}

/**
 * 模拟发出url请求
 * @param url 请求url
 * @param time 延迟ms
 * @returns Promise
 */
function request(url: string, time = 1000) {
  /* return new Promise<string>(async (resolve, reject) => {
    try {
      console.log(url, time);
      const res = await fetch("/api_student/students");
      const data = await res.json();
      resolve(data);
    } catch (error) {
      reject(error);
    }
  }); */
  return new Promise<string>((resolve, reject) => {
    setTimeout(() => {
      console.log(url, time);
      if (Math.random() > 0.5) {
        resolve("成功");
      } else {
        reject("失败");
      }
    }, time);
  });
}

/* // 测试
sendRequest(["http1", "http2", "http3", "http4", "http5", "http6", "http7"], 4, res => {
  console.log("执行回调函数", res);
}); */
